﻿using System;
using System.Collections.Generic;
using System.Drawing;
using LevelEditor.Document;

namespace LevelEditor.View
{
    public class LayerView
    {
        #region Properties

        public Size Size { get; set; }

        public Layer Layer { get; set; }

        public List<Bitmap> TileSetImages { get; set; }

        #endregion

        #region Constructors

        public LayerView(Layer layer)
        {
            TileSetImages = new List<Bitmap>();
            if (layer == null)
                throw new NullReferenceException();
            Layer = layer;
            Reset();
        }

        #endregion

        ~LayerView()
        {
            foreach (Bitmap b in TileSetImages)
                if (b != null)
                    b.Dispose();
        }

        #region Methods

        public void CheckSize()
        {
            Size = Layer.Size;
        }

        public void Reset()
        {
            // Resize tile lists
            CheckSize();
            RebuildTileSetImages();
        }

        public void CheckTiles()
        {
            List<Point> keys = new List<Point>();
            foreach (KeyValuePair<Point, Tile> pair in Layer.Tiles)
                if (pair.Value.TileSetIndex >= Layer.TileSets.Count)
                    keys.Add(pair.Key);
            foreach (Point p in keys)
                Layer.Tiles.Remove(p);
        }

        private Bitmap BuildTileSetAt(int index)
        {
            Image image = ImageManager.GetInstance().GetImageByName(Layer.TileSets[index].ImageFileName);
            Size bitmapTileSize = new Size();
            bitmapTileSize.Width = image.Width / Layer.TileSize.Width;
            bitmapTileSize.Height = image.Height / Layer.TileSize.Height;
            if (image.Width % Layer.TileSize.Width != 0)
                ++bitmapTileSize.Width;
            if (image.Height % Layer.TileSize.Height != 0)
                ++bitmapTileSize.Height;
            bitmapTileSize.Width *= Layer.TileSize.Width;
            bitmapTileSize.Height *= Layer.TileSize.Height;
            Bitmap bitmap = new Bitmap(bitmapTileSize.Width, bitmapTileSize.Height);
            Graphics g = Graphics.FromImage(bitmap);
            g.Transform.Reset();
            g.DrawImageUnscaled(image, Point.Empty);
            g.Dispose();
            return bitmap;
        }

        public void RebuildTileSetAt(int index)
        {
            Bitmap bitmap = BuildTileSetAt(index);
            while (TileSetImages.Count < Layer.TileSets.Count)
                TileSetImages.Add(null);
            while (TileSetImages.Count > Layer.TileSets.Count)
            {
                TileSetImages[TileSetImages.Count - 1].Dispose();
                TileSetImages.RemoveAt(TileSetImages.Count - 1);
            }
            if (TileSetImages[index] != null)
                TileSetImages[index].Dispose();
            TileSetImages[index] = bitmap;
        }

        public void RebuildTileSetImages()
        {
            foreach (Bitmap b in TileSetImages)
                b.Dispose();
            TileSetImages.Clear();
            for (int i = 0; i < Layer.TileSets.Count; ++i)
            {
                TileSetImages.Add(BuildTileSetAt(i));
            }
        }

        public Rectangle GetPaletteSourceRectFromTile(Tile tile)
        {
            Rectangle rect = Rectangle.Empty;
            int tileWidth = TileSetImages[tile.TileSetIndex].Width / Layer.TileSize.Width;
            rect.X = (tile.TileIndex % tileWidth) * Layer.TileSize.Width;
            rect.Y = tile.TileIndex / tileWidth * Layer.TileSize.Height;
            rect.Size = Layer.TileSize;
            return rect;
        }

        public int GetIndexLimitForTile(Tile tile)
        {
            return TileSetImages[tile.TileSetIndex].Width / Layer.TileSize.Width * 
                TileSetImages[tile.TileSetIndex].Height / Layer.TileSize.Height;
        }

        public void Draw(Graphics g)
        {
            //for (int x = 0; x < Size.Width; ++x)
            //{
            //    for (int y = 0; y < Size.Height; ++y)
            //    {
            //        Rectangle destRectangle = new Rectangle(x * Layer.TileSize.Width, y * Layer.TileSize.Height, 
            //            Layer.TileSize.Width, Layer.TileSize.Height);
            //        if(g.IsVisible(destRectangle))
            //            g.DrawImage(TileSetImages[Layer.TilesOld[x][y].TileSetIndex], 
            //                destRectangle, GetPaletteSourceRectFromTile(Layer.TilesOld[x][y]), 
            //                GraphicsUnit.Pixel);
            //    }
            //}
            foreach (KeyValuePair<Point, Tile> pair in Layer.Tiles)
            {
                Rectangle destRectangle =
                    new Rectangle(pair.Key.X * Layer.TileSize.Width,
                        pair.Key.Y * Layer.TileSize.Height,
                        Layer.TileSize.Width, Layer.TileSize.Height);
                if (g.IsVisible(destRectangle))
                    g.DrawImage(TileSetImages[pair.Value.TileSetIndex], destRectangle, 
                        GetPaletteSourceRectFromTile(pair.Value), GraphicsUnit.Pixel);
            }
        }

        #endregion
    }
}
